1. Field of the Invention
The present invention relates to computers and computer software. More specifically, the invention is generally related to debugging software.
2. Background of the Related Art
Inherent in any software development technique is the potential for introducing xe2x80x9cbugsxe2x80x9d. A bug will typically cause unexpected results during the execution of the program. Locating, analyzing, and correcting bugs in a computer program is a process known as xe2x80x9cdebugging.xe2x80x9d Debugging of programs may be done either manually or interactively by a debugging system mediated by a computer system. Manual debugging of a program requires a programmer to manually trace the logic flow of the program and the contents of memory elements, e.g., registers and variables. In the interactive debugging of programs, the program is executed under the control of a monitor program (known as a xe2x80x9cdebuggerxe2x80x9d), commonly located on and executed by the same computer system on which the program is executed,
Conventional debuggers typically support two primary operations to assist a computer programmer. Each operation allows the programmer to examine the state of program registers and variables at a given point in the execution of a program. A first operation supported by conventional debuggers is a xe2x80x9cstepxe2x80x9d function, which permits a computer programmer to process instructions in a computer program at a source file level (i.e., line by line) and at a statement level, and see the results upon completion of each instruction. While the step operation provides a programmer with a large amount of information about a program during its execution, stepping through hundreds or thousands of program instructions can be extremely tedious and time consuming. A programmer may be required to step through many program instructions that are known to be error-free before a set of instructions to be analyzed are executed.
A second operation supported by conventional debuggers is a breakpoint operation. A xe2x80x9cbreakpointxe2x80x9d is a point in the program where execution of the computer program is stopped so that the state of the program can be examined by a computer programmer. As a result, when a computer program is executed by a debugger, the program executes in a normal fashion until a breakpoint is reached. The debugger then stops execution and displays the results of the computer program to the programmer for analysis.
Most breakpoints supported by conventional debuggers are unconditional, meaning that once such a breakpoint is reached, execution of the program is always halted. Some debuggers also support the use of conditional breakpoints, which only halt execution of a program when a variable used by the program is set to a predetermined value at the time such a breakpoint is reached.
Typically, step operations and breakpoints are used together to simplify the debugging process. Specifically, a common debugging operation is to set a breakpoint at the beginning of a desired set of instructions to be analyzed, and then execute the program. Once the breakpoint is reached, the program is halted, and the programmer then steps through the desired set of instructions line by line using the step operation. Consequently, a programmer is able to isolate and analyze a particular set of instructions without having to step through irrelevant portions of a computer program.
One of the most difficult problems to debug is when a program reads from uninitialized memory. As a program code is converted into binary instructions, memory for variables is set aside. Uninitialized memory refers to memory that is not given initial values. Problems with uninitialized memory can manifest themselves in different ways, costing loss of programmer productivity. For example, variables may be assigned random values when they are uninitialized that cause errors which are not immediately transparent.
One attempt to debug memory-related errors is to purposefully introduce a xe2x80x9cfunny value,xe2x80x9d or garbage, into the memory. In some cases, the funny value will be utilized during the execution of the program and result in output alerting the programmer to a potential memory related problem. However, in practice, the funny value selected by the programmer does not necessarily produce an expected error. Thus, the programmer can never be certain that a given output is the result of the funny value being accessed from memory. In addition, even when recognizable output is produced, the output often does not occur until much later in the execution of the program relative to when the funny value was actually used. Thus, the programmer is unable to determine where in the source code the error is located.
Another method which can be used to locate the location of a read from uninitialized memory limited situations is a compiler generated warning message notifying the user of the reference to the memory. However, this method does not detect all references to uninitialized memory. This limitation results because modules are compiled separately so the compiler doesn""t xe2x80x9cknowxe2x80x9d what variables may be set by a call to a procedure in another module. Further, variable values that affect control flow can come from sources external to the compiler such as data files and user input. As a result, it is impossible for the compiler to diagnose anything but the simplest of situations where a variable is referenced before its value is set.
In another method, referred to herein as the xe2x80x9cobject code insertionxe2x80x9d (xe2x80x9cOCIxe2x80x9d) method, checking instructions are inserted in the program""s object files, between instructions that reference memory, to monitor the program""s memory reads and writes. The executable contains a call to malloc and a reference of the allocated memory. After the call to malloc and before the following memory-reference instruction, control transfers to a checking function and then returns at its conclusion to the original executable. This method also uses a malloc wrapper to monitor the program""s memory allocations and frees.
One problem with the OCI method is that it requires a special build of the program, in which checking instructions are inserted between the program""s normal instructions. The OCI method also suffers from performance degradation because performing a function call and looking up data structures during every memory-reference instruction in a program will necessarily have a severe impact on performance. Experienced users may often intuit that uninitialized memory is being referenced. In this case, the users don""t require that all memory being allocated in the program be tested as is done with the OCI method. Rather, the user requires a method and apparatus to pinpoint the exact location of the reference on the suspect memory space.
Moreover, the OCI method performs function calls and data structure references in-between a program""s normal instructions, which results in poor locality and few cache hits on modern CPU architectures that utilize on-chip caches, resulting in further performance degradation. In addition, the OCI method provides excessive information, requiring more overhead time on the part of the user to sift through the output data to locate relevant information.
Therefore, there is a need for a debugging program adapted to address the problems associated with uninitialized memory.
The present invention generally provides an apparatus, program product, and a method for debugging computer programs that monitors reads and writes to uninitialized memory.
In one aspect of the invention, a method for debugging code is provided, comprising, setting an uninitialized memory control point on at least one memory space, wherein the uninitialized memory control point is adapted to cause detection of a reference to the memory space during execution of the code. When the reference is made to the memory space during execution of the code, the method determines whether the memory space is initialized; and if the memory space is not initialized when the reference is made, a result is returned to a user interface indicating that the reference was made.
In another aspect of the invention, a method for debugging code is provided, comprising, allocating at least one memory space having a memory address range and setting an uninitialized memory watch on the memory space, which is triggered when a reference is made to the memory space. If the reference is a write, a first Dcode is executed to mark the memory space as initialized. If the reference is a read, a second Dcode is executed to determine whether the memory space is initialized. If the memory space is not initialized when the read is made, a result is returned to a user interface indicating the reference.
In another aspect of the invention, a program product comprising a computer readable medium bearing a debugging program is provided. When executed the debugging program causes steps to be performed, the steps comprising, allocating at least one memory space in a memory and setting an uninitialized memory watch on the memory space, which is triggered when a reference is made to the memory space during execution of a target program. If the reference is a write, a first Dcode is executed to mark the memory space as initialized. If the reference is a read, a second Dcode is executed to determine whether the memory space is initialized. If the memory space is not initialized when the read is made, a result is returned to a user interface indicating the reference.
In another aspect of the invention, a computer system comprising a memory and a processor configured for providing a system exception in response to references to the memory is provided wherein a method debugging a program is executing in the processor. The method comprises allocating at least one memory space in the memory; setting an uninitialized memory watch on the memory space, wherein when a reference is made to the memory space the uninitialized memory watch is triggered and causes the processor to provide the system exception; executing, by the processor, a first Dcode to mark the memory space as initialized if the reference is a write; and executing, by the processor, a second Dcode to determine whether the memory space is initialized if the reference is a read. If the memory space is not initialized when the read is made, a result is returned to a user interface indicating the reference.